package com.gzz.demo.multithread.thread;

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {

	public static class Worker extends Thread {
		private CyclicBarrier barrier;
		private CountDownLatch latch;

		public Worker(CyclicBarrier barrier, CountDownLatch latch) {
			super();
			this.barrier = barrier;
			this.latch = latch;
		}

		@Override
		public void run() {
			System.out.println(this + " is going to company...");
			Random ran = new Random();
			try {
				Thread.sleep(ran.nextInt(3000));
			} catch (InterruptedException e1) {
				e1.printStackTrace();
				return;
			}
			try {
				int index = barrier.await(); // wait other workers
				System.out.println(this + " is the "
						+ (barrier.getParties() - index)
						+ " one got to company");
			} catch (InterruptedException e) {
				e.printStackTrace();
				return;
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
				return;
			}

			// working
			try {
				Thread.sleep(ran.nextInt(10000));
			} catch (InterruptedException e1) {
				e1.printStackTrace();
				return;
			}
			try {
				int index = barrier.await(); // wait other workers
				System.out.println(this + " is the "
						+ (barrier.getParties() - index) + " one finished job");
			} catch (InterruptedException e) {
				e.printStackTrace();
				return;
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
				return;
			}
			latch.countDown();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		int workerCount = 5;
		CountDownLatch latch = new CountDownLatch(5);
		CyclicBarrier barrier = new CyclicBarrier(workerCount, new Runnable() {

			@Override
			public void run() {
				System.out.println(Thread.currentThread() + " arrive barrier");
			}

		});

		for (int i = 0; i < workerCount; ++i) {
			new Worker(barrier, latch).start();
		}

		latch.await();// wait all worker finished
	}
}